home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EuroCD 3
/
EuroCD 3.iso
/
Programming
/
vbcc
/
alias.c
next >
Wrap
C/C++ Source or Header
|
1998-06-24
|
12KB
|
311 lines
/* $VER: vbcc (alias.c) V0.4 */
/* Listen benutzter/veraenderter Variablen und Behandlung von Decknamen. */
#include "opt.h"
static char FILE_[]=__FILE__;
int p_typ(struct Var *v)
/* Liefert den Typ, auf den Variable zeigen kann. Falls nicht eindeutig */
/* wird CHAR zurueckgegeben, da ein char * auf alles zeigen kann. */
{
struct Typ *t=v->vtyp;int f;
/* Kein Zeiger? Dann moeglicherweise Struktur, die verschiedene Zeiger */
/* enthalten koennte. Koennte man evtl. noch genauer pruefen. */
if((t->flags&NQ)!=POINTER||!t->next||(v->flags&DNOTTYPESAFE)) return(CHAR);
f=t->next->flags&NQ;
if(f==VOID) f=CHAR;
return(f);
}
void ic_changes(struct IC *p,unsigned char *result)
/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
/* IC p geaendert werden koennten. */
{
int i,j,t,t2;struct Var *v;
memset(result,0,vsize);
t=p->typf&NQ;
if(p->z.flags&VAR){
v=p->z.v;
i=v->index;
/* Hilfsvariable, die waehrend diesem cse-Durchlauf eingefuehrt */
/* wurde. */
if(i<0) return;
if(p->z.flags&DREFOBJ) i+=vcount-rcount;
if(i>=vcount) ierror(0);
BSET(result,i);
/* Wenn p geaendert wird, wird auch *p geaendert */
if(i<rcount) BSET(result,i+vcount-rcount);
if(p->z.flags&DREFOBJ){
if(noaliasopt){
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
}else{
for(j=0;j<vcount-rcount;j++){
v=vilist[j];
if(!v) ierror(0);
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
struct Typ *tp=v->vtyp;
if(!v->vtyp) ierror(0);
do{
t2=tp->flags&NQ;
tp=tp->next;
}while(t2==ARRAY);
if(t==t2||t==CHAR||t2>POINTER){
BSET(result,j);
if(j<rcount) BSET(result,j+vcount-rcount);
continue;
}
}
if(j<rcount){
t2=p_typ(v);
if(t==t2||t==CHAR||t2==CHAR||t2>POINTER) BSET(result,j+vcount-rcount);
}
}
}
}else{
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
if(noaliasopt){
bvunite(result,av_drefs,vsize);
}else{
for(j=0;j<rcount;j++){
t2=p_typ(vilist[j]);
if(t==t2||t2==CHAR||t>POINTER) BSET(result,j+vcount-rcount);
}
}
}
}
}
if(p->code==CALL){
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
bvunite(result,av_statics,vsize);
}
}
void ic_uses(struct IC *p,unsigned char *result)
/* Initialisiert den Bitvektor result mit allen Variablen, die durch das */
/* IC p benutzt werden koennten. */
{
int i,j,t,t2,c;struct Var *v;struct Typ *tp;
memset(result,0,vsize);
c=p->code;t=p->typf&NQ;
if(c!=ADDRESS){
if((p->q1.flags&(VAR|VARADR))==VAR){
v=p->q1.v;
i=v->index;
if(c==ADDI2P||c==SUBIFP||c==SUBPFP) t=POINTER;
if(c==CONVCHAR||c==CONVUCHAR) t=CHAR;
if(c==CONVSHORT||c==CONVUSHORT) t=SHORT;
if(c==CONVINT||c==CONVUINT) t=INT;
if(c==CONVLONG||c==CONVULONG) t=LONG;
if(c==CONVFLOAT) t=FLOAT;
if(c==CONVDOUBLE) t=DOUBLE;
if(c==CONVPOINTER) t=POINTER;
if(i>=vcount) {pric2(stdout,p);ierror(0);}
BSET(result,i);
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
if(noaliasopt){
bvunite(result,av_drefs,vsize);
}else{
for(j=0;j<rcount;j++){
t2=p_typ(vilist[j]);
if(t==t2||t2==CHAR||t>POINTER) BSET(result,j+vcount-rcount);
}
}
}
if(p->q1.flags&DREFOBJ){
BSET(result,i+vcount-rcount);
if(noaliasopt){
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
}else{
for(j=0;j<vcount-rcount;j++){
v=vilist[j];
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
tp=v->vtyp;
do{
t2=tp->flags&NQ;
tp=tp->next;
}while(t2==ARRAY);
if(t==t2||t==CHAR||t2>POINTER||t>POINTER) BSET(result,j);
}
if(j<rcount){
t2=p_typ(v);
if(t==t2||t==CHAR||t2==CHAR||t>POINTER) BSET(result,j+vcount-rcount);
}
}
}
}
}
if((p->q2.flags&(VAR|VARADR))==VAR){
v=p->q2.v;
i=v->index;
if(c==SUBPFP) t=POINTER;
if(i>=vcount) {pric2(stdout,p);ierror(0);}
BSET(result,i);
if(v->nesting==0||(v->flags&USEDASADR)){
if(noaliasopt){
bvunite(result,av_drefs,vsize);
}else{
for(j=0;j<rcount;j++){
t2=p_typ(vilist[j]);
if(t==t2||t2==CHAR||t>POINTER) BSET(result,j+vcount-rcount);
}
}
}
if(p->q2.flags&DREFOBJ){
BSET(result,i+vcount-rcount);
if(noaliasopt){
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
}else{
for(j=0;j<vcount-rcount;j++){
v=vilist[j];
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
tp=v->vtyp;
do{
t2=tp->flags&NQ;
tp=tp->next;
}while(t2==ARRAY);
if(t==t2||t==CHAR||t2>POINTER) BSET(result,j);
}
if(j<rcount){
t2=p_typ(v);
if(t==t2||t==CHAR||t2==CHAR) BSET(result,j+vcount-rcount);
}
}
}
}
}
}
if((p->z.flags&(VAR|VARADR|DREFOBJ))==(VAR|DREFOBJ)){
v=p->z.v;
i=v->index;
if(i>=vcount) {pric2(stdout,p);ierror(0);}
BSET(result,i);
if(c==ADDI2P||c==SUBIFP) t=POINTER;
if(v->nesting==0||v->storage_class==EXTERN||(v->flags&USEDASADR)){
if(noaliasopt){
bvunite(result,av_drefs,vsize);
}else{
for(j=0;j<rcount;j++){
t2=p_typ(vilist[j]);
if(t==t2||t2==CHAR||t>POINTER||t2>POINTER) BSET(result,j+vcount-rcount);
}
}
}
}
if(p->code==CALL){
bvunite(result,av_drefs,vsize);
bvunite(result,av_address,vsize);
bvunite(result,av_globals,vsize);
bvunite(result,av_statics,vsize);
}
}
void free_alias(struct flowgraph *fg)
/* Gibt alle use/change-Listen der ICs im Flussgraphen frei. */
{
struct IC *p;struct flowgraph *g;
if(DEBUG&1024) printf("freeing alias info\n");
for(g=fg;g;g=g->normalout){
for(p=g->start;p;p=p->next){
if(p->code==LABEL&&(p->use_cnt>0||p->change_cnt>0)) ierror(0);
if(p->use_cnt>0) free(p->use_list);
if(p->change_cnt>0) free(p->change_list);
if(p==g->end) break;
}
}
have_alias=0;
}
void create_alias(struct flowgraph *fg)
/* Initialisiert jedes IC mit einer Liste aller Variablen, die dadurch */
/* benutzt und veraendert werden koennten. Z.Z. wird bis auf Typ-basierte */
/* Optimierungen der worst-case angenommen. */
{
unsigned char *vars=mymalloc(vsize);
struct IC *p;struct flowgraph *g;
int i,cnt;
if(DEBUG&1024) printf("creating alias info\n");
for(g=fg;g;g=g->normalout){
for(p=g->start;p;p=p->next){
ic_uses(p,vars);
for(i=0,cnt=0;i<vcount;i++)
if(BTST(vars,i)) cnt++;
p->use_cnt=cnt;
if(cnt==0){
p->use_list=0;
}else{
p->use_list=mymalloc(cnt*VLS);
for(cnt=0,i=0;i<vcount;i++){
if(BTST(vars,i)){
p->use_list[cnt].v=vilist[i];
if(i>=vcount-rcount) p->use_list[cnt].flags=DREFOBJ;
else p->use_list[cnt].flags=0;
cnt++;
}
}
}
ic_changes(p,vars);
for(i=0,cnt=0;i<vcount;i++)
if(BTST(vars,i)) cnt++;
p->change_cnt=cnt;
if(cnt==0){
p->change_list=0;
}else{
p->change_list=mymalloc(cnt*VLS);
for(cnt=0,i=0;i<vcount;i++){
if(BTST(vars,i)){
p->change_list[cnt].v=vilist[i];
if(i>=vcount-rcount) p->change_list[cnt].flags=DREFOBJ;
else p->change_list[cnt].flags=0;
cnt++;
}
}
}
if(p==g->end) break;
}
}
free(vars);
have_alias=1;
}
void update_alias(struct Var *old,struct Var *new)
/* Aendert alle use/changes von (old) auf (new). Wird aufgerufen, wenn */
/* copy-propagation eine Variable neu zu einem DREFOBJ macht. */
{
struct IC *p;int i;
void *m;
if(DEBUG&1024) printf("update-alias\n");
for(p=first_ic;p;p=p->next){
for(i=0;i<p->use_cnt;i++){
if(p->use_list[i].v==old&&(p->use_list[i].flags&DREFOBJ)){
m=p->use_list;
p->use_cnt++;
p->use_list=mymalloc(p->use_cnt*VLS);
p->use_list[0].v=new;
p->use_list[0].flags=DREFOBJ;
memcpy(&p->use_list[1],m,(p->use_cnt-1)*VLS);
free(m);
break;
}
}
for(i=0;i<p->change_cnt;i++){
if(p->change_list[i].v==old&&(p->change_list[i].flags&DREFOBJ)){
m=p->change_list;
p->change_cnt++;
p->change_list=mymalloc(p->change_cnt*VLS);
p->change_list[0].v=new;
p->change_list[0].flags=DREFOBJ;
memcpy(&p->change_list[1],m,(p->change_cnt-1)*VLS);
free(m);
break;
}
}
}
}